use std::any::Any;
use std::fmt::Debug;

use pest_derive::Parser;
use pest::Parser;
use pest::iterators::Pair;

#[derive(Parser)]
#[grammar = "lexer.pest"]
pub struct ExpressionParser;

#[derive(Debug, PartialEq)]
pub enum Token {
    Integer(i64, String, usize),  // 值、原始文本、行号
    Operator(String, String, usize),      // 子类型、运算符文本、行号
    Keyword(String, String, usize),       // 子类型、关键字文本、行号
    Identifier(String, usize),            // 标识符文本、行号
    Symbol(String, String, usize),        // 子类型、符号文本、行号
    Whitespace,
    Comment,
    EOI
}

type TokenResult = Result<Vec<Token>, Vec<(usize, String)>>; // 错误类型包含行号和错误信息

// 获取Pest对象的行号
fn get_line_number(pair: &Pair<Rule>) -> usize {
    pair.line_col().0
}

pub fn tokenize(input: &str) -> TokenResult {
    let mut errors = Vec::new();
    let mut tokens = Vec::new();
    
    // 尝试解析整个输入
    let pairs =  ExpressionParser::parse(Rule::expr, input).expect("parser should not fail");

    let pair = pairs.into_iter().next().unwrap(); // 获取主表达式
    
    // 遍历所有匹配的规则
    for p in pair.into_inner() {
        let line_num = get_line_number(&p);
        // println!("{:?} at line {}", p, line_num); // 调试输出

        match p.as_rule() {
            Rule::INTEGER_CONST => {
                let s = p.as_str();
                let original_text = s.to_string();
                let value = if s.starts_with("0x") || s.starts_with("0X") {
                    // 十六进制处理
                    i64::from_str_radix(&s[2..], 16)
                } else if s.starts_with("0") && s.len() > 1 {
                    // 八进制处理
                    i64::from_str_radix(&s[1..], 8)
                } else {
                    // 十进制处理
                    s.parse::<i64>()
                };
                
                match value {
                    Ok(v) => tokens.push(Token::Integer(v, original_text, line_num)),
                    Err(_e) => errors.push((line_num, "Invalid integer format".to_string())), // 捕获解析错误
                }
            },
            Rule::op => {
                let operator_text = p.as_str().to_string();
                tokens.push(Token::Operator(format!("{:?}", p.into_inner().next().unwrap().as_rule()), operator_text, line_num));
            },
            Rule::WHITESPACE => {
                tokens.push(Token::Whitespace);
            },
            Rule::COMMENT => {
                tokens.push(Token::Comment);
            },
            Rule::keyword => {
                let keyword_text = p.as_str().to_string();
                tokens.push(Token::Keyword(format!("{:?}", p.into_inner().next().unwrap().as_rule()), keyword_text, line_num));
            },
            Rule::IDENT => {
                tokens.push(Token::Identifier(p.as_str().to_string(), line_num));
            },
            Rule::symbol => {
                let symbol_text = p.as_str().to_string();
                tokens.push(Token::Symbol(format!("{:?}", p.into_inner().next().unwrap().as_rule()), symbol_text, line_num));
            },
            Rule::EOI => {
                tokens.push(Token::EOI);
            },
            Rule::error => {
                // 捕获未识别的输入作为错误
                errors.push((line_num, p.as_str().to_string()));
            },
            _ => unreachable!(),
        }
    }
    
    if errors.is_empty() {
        Ok(tokens)
    } else {
        Err(errors)
    }
}